package com.xb.cloud.shopping.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.xb.cloud.common.JsonUtils;
import com.xb.cloud.common.client.TimeService;
import com.xb.cloud.common.constant.DbConstants;
import com.xb.cloud.common.model.ShopType;
import com.xb.cloud.common.util.BeanUtils;
import com.xb.cloud.common.util.StringUtils;
import com.xb.cloud.gateway.client.ReturnCodes;
import com.xb.cloud.gateway.client.ReturnUtils;
import com.xb.cloud.gateway.client.RtnInfo;
import com.xb.cloud.order.service.client.ProductStockService;
import com.xb.cloud.product.merchant.service.client.ShopService;
import com.xb.cloud.product.merchant.service.client.bo.ProductSkuBo;
import com.xb.cloud.product.merchant.service.client.bo.ShopSkuBo;
import com.xb.cloud.product.service.client.SkuService;
import com.xb.cloud.service.client.ServiceReturnInfo;
import com.xb.cloud.service.client.ServiceReturnUtils;
import com.xb.cloud.shopping.client.vo.ShopSkuCartItemVo;
import com.xb.cloud.shopping.client.vo.ShoppingCartQueryVo;
import com.xb.cloud.shopping.client.vo.SkuCartItemVo;
import com.xb.cloud.shopping.model.ShoppingCart;
import com.xb.cloud.shopping.model.ShoppingCartItem;
import com.xb.cloud.shopping.service.ShoppingCartApiService;
import com.xb.cloud.user.service.client.ShoppingCartService;
import com.xb.cloud.user.service.client.bo.EndUserCartBo;
import com.xb.cloud.user.service.client.bo.ProductSkuStockBo;

/**
 * 
 * @ClassName: ShoppingCartApiServiceImpl
 * @Description:购物车api接口类
 * @author: 鲜备科技
 * @date: 2018年1月17日 上午11:44:10
 * 
 * @Copyright: 2018 www.xianbeitech.com Inc. All rights reserved.
 *
 */
@Service
public class ShoppingCartApiServiceImpl implements ShoppingCartApiService {

	@Resource
	TimeService timeService;

	@Resource
	ShoppingCartService shoppingCartService;

	@Resource
	ShopService shopService;

	@Resource
	SkuService skuService;

	@Resource
	ProductStockService productStockService;

	/**
	 * 获取用户购物车，商品列表
	 * 
	 * @Title getUserCartInfo
	 * @param userShoppingCartVo
	 * @return
	 */
	@Override
	public RtnInfo getUserCartInfo(ShoppingCartQueryVo userShoppingCartVo) {
		EndUserCartBo endUserCartBo = new EndUserCartBo();
		endUserCartBo.setCompanyId(userShoppingCartVo.getCompanyId());
		endUserCartBo.setEndUserId(userShoppingCartVo.getCurrentUserId());

		EndUserCartBo endUserCart = shoppingCartService.getEndUserCart(endUserCartBo);

		ShoppingCart shoppingCart = new ShoppingCart();
		shoppingCart.setEndUserId(userShoppingCartVo.getCurrentUserId());

		if (endUserCart == null || "[]".equals(endUserCart.getCartValues())) {
			return ReturnUtils.success(shoppingCart);
		} else {
			String cartValues = endUserCart.getCartValues();
			List<ShoppingCartItem> itemList = JsonUtils.toObjectArray(cartValues, ShoppingCartItem.class);

			List<Long> skuIdList = new ArrayList<>();// 用于查询sku
			for (ShoppingCartItem shoppingCartItem : itemList) {
				skuIdList.add(shoppingCartItem.getSkuId());
			}

			List<ShopSkuBo> shopSkuList = skuService.getShopSkuListBySkuIds(skuIdList);

			Map<Long, ShopSkuBo> shopSkuMap = new HashMap<>();
			for (ShopSkuBo shopSkuBo : shopSkuList) {
				shopSkuMap.put(shopSkuBo.getSkuId(), shopSkuBo);
			}

			List<ShopSkuCartItemVo> shopItems = new ArrayList<>();
			Map<Long, ShopSkuCartItemVo> shopSkuItemMap = new HashMap<>();

			int skuCount = 0;
			for (ShoppingCartItem shoppingCartItem : itemList) {
				Long skuId = shoppingCartItem.getSkuId();
				Date addTime = shoppingCartItem.getAddTime();
				int num = shoppingCartItem.getNum();

				ShopSkuBo shopSkuBo = shopSkuMap.get(skuId);
				Long shopId = shopSkuBo.getShopId();
				List<SkuCartItemVo> skuItems = null;
				ShopSkuCartItemVo shopSkuCartItemVo = shopSkuItemMap.get(shopId);
				if (shopSkuCartItemVo == null) {
					shopSkuCartItemVo = new ShopSkuCartItemVo();
					shopSkuCartItemVo.setShopId(String.valueOf(shopSkuBo.getShopId()));
					shopSkuCartItemVo.setShopHomeUrl(shopSkuBo.getShopHomeUrl());
					shopSkuCartItemVo.setShopLogoUrl(shopSkuBo.getShopLogoUrl());
					shopSkuCartItemVo.setShopNameCn(shopSkuBo.getShopNameCn());
					String shopTypeName = "";
					if (shopSkuBo.getShopType() != null) {
						int shopType = shopSkuBo.getShopType();
						shopTypeName = ShopType.getEnumByCode(shopType).getName();
					}
					shopSkuCartItemVo.setShopType(shopTypeName);
					shopSkuItemMap.put(shopId, shopSkuCartItemVo);
					shopItems.add(shopSkuCartItemVo);

					skuItems = new ArrayList<>();
					SkuCartItemVo skuCartItemVo = BeanUtils.newAndCopyProperties(SkuCartItemVo.class, shopSkuBo);
					skuCartItemVo.setAddTime(addTime);
					skuCartItemVo.setNum(num);
					skuItems.add(skuCartItemVo);
					shopSkuCartItemVo.setItems(skuItems);
				} else {
					skuItems = shopSkuCartItemVo.getItems();
					SkuCartItemVo skuCartItemVo = BeanUtils.newAndCopyProperties(SkuCartItemVo.class, shopSkuBo);
					skuCartItemVo.setAddTime(addTime);
					skuCartItemVo.setNum(num);
					skuItems.add(skuCartItemVo);
				}

				skuCount += num;
			}

			shoppingCart.setShopItems(shopItems);
			shoppingCart.setSkuCount(skuCount);
			shoppingCart.setItemCount(itemList.size());

			return ReturnUtils.success(shoppingCart);
		}
	}

	/**
	 * 购物车添加商品
	 * 
	 * @Title addSku
	 * @param userShoppingCartVo
	 * @return
	 */
	@Override
	public RtnInfo addSkuToCart(ShoppingCartQueryVo userShoppingCartVo) {
		Long skuId = userShoppingCartVo.getSkuId();
		int num = userShoppingCartVo.getNum();
		ShoppingCartItem shoppingCartItem = new ShoppingCartItem(skuId, num);

		EndUserCartBo endUserCartBo = new EndUserCartBo();
		endUserCartBo.setCompanyId(userShoppingCartVo.getCompanyId());
		endUserCartBo.setEndUserId(userShoppingCartVo.getCurrentUserId());
		EndUserCartBo endUserCart = shoppingCartService.getEndUserCart(endUserCartBo);
		
		if (endUserCart == null) {
			RtnInfo rtnInfo = checkSkuAndStock(skuId, num);
			if (ReturnUtils.isError(rtnInfo)) {
				return rtnInfo;
			}
			
			Date addTime = timeService.getDate();
			shoppingCartItem.setAddTime(addTime);
			endUserCartBo.setCartValues(JsonUtils.beanToJson(Arrays.asList(shoppingCartItem)));
			shoppingCartService.createEndUserCart(endUserCartBo);
			
		} else {
			String cartValues = endUserCart.getCartValues();
			List<ShoppingCartItem> itemList = JsonUtils.toObjectArray(cartValues, ShoppingCartItem.class);

			Iterator<ShoppingCartItem> iterator = itemList.iterator();
			boolean contain = false;
			while (iterator.hasNext()) {
				ShoppingCartItem item = iterator.next();
				if (skuId.equals(item.getSkuId())) {
					// 如果购物车里已经有此商品数量
					contain = true;
					iterator.remove();
					shoppingCartItem.setNum(item.getNum() + num);
					break;
				}
			}
			
			RtnInfo rtnInfo = checkSkuAndStock(skuId, shoppingCartItem.getNum());
			if (ReturnUtils.isError(rtnInfo)) {
				return rtnInfo;
			}
			
			if (!contain) {
				// 新增商品到购物车
				Date addTime = timeService.getDate();
				shoppingCartItem.setAddTime(addTime);
			}
			
			itemList.add(0, shoppingCartItem);
			endUserCart.setCartValues(JsonUtils.beanToJson(itemList));
			shoppingCartService.updateCartValues(endUserCart);
		}

		return ReturnUtils.success();
	}

	/**
	 * 更新购物车商品数量
	 * 
	 * @Title updateItemNum
	 * @param userShoppingCartVo
	 * @return
	 */
	@Override
	public RtnInfo updateItemNum(ShoppingCartQueryVo userShoppingCartVo) {

		Long skuId = userShoppingCartVo.getSkuId();
		int num = userShoppingCartVo.getNum();

		RtnInfo rtnInfo = checkSkuAndStock(skuId, num);
		if (ReturnUtils.isError(rtnInfo)) {
			return rtnInfo;
		}

		EndUserCartBo endUserCartBo = new EndUserCartBo();
		endUserCartBo.setCompanyId(userShoppingCartVo.getCompanyId());
		endUserCartBo.setEndUserId(userShoppingCartVo.getCurrentUserId());

		EndUserCartBo endUserCart = shoppingCartService.getEndUserCart(endUserCartBo);
		if (endUserCart == null) {
			return ReturnUtils.error(null);
		} else {
			String cartValues = endUserCart.getCartValues();
			List<ShoppingCartItem> itemList = JsonUtils.toObjectArray(cartValues, ShoppingCartItem.class);
			boolean contain = false;
			for (ShoppingCartItem shoppingCartItem : itemList) {
				if (skuId.equals(shoppingCartItem.getSkuId())) {
					contain = true;
					shoppingCartItem.setNum(num);
					break;
				}
			}

			if (!contain) {
				// TODO:商品已经删除怎么处理
			} else {
				endUserCart.setCartValues(JsonUtils.beanToJson(itemList));
				shoppingCartService.updateCartValues(endUserCart);
			}
		}

		return ReturnUtils.success();
	}

	/**
	 * 获取购物车商品数量，用于显示购物车商品总数量
	 * 
	 * @Title getCartNum
	 * @param userShoppingCartVo
	 * @return
	 */
	@Override
	public RtnInfo getCartNum(ShoppingCartQueryVo userShoppingCartVo) {
		EndUserCartBo endUserCartBo = new EndUserCartBo();
		endUserCartBo.setCompanyId(userShoppingCartVo.getCompanyId());
		endUserCartBo.setEndUserId(userShoppingCartVo.getCurrentUserId());

		EndUserCartBo endUserCart = shoppingCartService.getEndUserCart(endUserCartBo);
		if (endUserCart == null) {
			return ReturnUtils.success(0);
		} else {
			String cartValues = endUserCart.getCartValues();
			List<ShoppingCartItem> itemList = JsonUtils.toObjectArray(cartValues, ShoppingCartItem.class);
			int count = 0;
			for (ShoppingCartItem shoppingCartItem : itemList) {
				count += shoppingCartItem.getNum();
			}

			return ReturnUtils.success(count);
		}
	}

	/**
	 * 根据skuId列表删除用户购物车里的商品
	 * 
	 * @Title deleteSkus
	 * @param userShoppingCartVo
	 * @param skuIds
	 * @return
	 */
	@Override
	public RtnInfo deleteSkus(ShoppingCartQueryVo userShoppingCartVo, String skuIds) {

		if (StringUtils.isEmpty(skuIds)) {

		} else {
			String[] ids = skuIds.split(",");
			List<String> skuIdList = Arrays.asList(ids);

			EndUserCartBo endUserCartBo = new EndUserCartBo();
			endUserCartBo.setCompanyId(userShoppingCartVo.getCompanyId());
			endUserCartBo.setEndUserId(userShoppingCartVo.getCurrentUserId());

			EndUserCartBo endUserCart = shoppingCartService.getEndUserCart(endUserCartBo);
			if (endUserCart == null) {
				return ReturnUtils.success(null);
			} else {
				String cartValues = endUserCart.getCartValues();
				List<ShoppingCartItem> itemList = JsonUtils.toObjectArray(cartValues, ShoppingCartItem.class);
				Iterator<ShoppingCartItem> iterator = itemList.iterator();
				while (iterator.hasNext()) {
					ShoppingCartItem item = iterator.next();
					if (skuIdList.contains(String.valueOf(item.getSkuId()))) {
						iterator.remove();
					}
				}

				endUserCart.setCartValues(JsonUtils.beanToJson(itemList));
				shoppingCartService.updateCartValues(endUserCart);
			}
		}

		return ReturnUtils.success();
	}

	/**
	 * 判断sku是否可售，库存是否足够
	 * 
	 * @Title checkSkuAndStock
	 * @param shoppingCartItem
	 * @return
	 */
	@Override
	public RtnInfo checkSkuAndStock(Long skuId, int num) {

		ProductSkuBo productSkuBo = skuService.getSkuById(skuId);
		if (productSkuBo == null) {
			return ReturnUtils.error(ReturnCodes.SKU_NOT_EXIST);
		} else {
			Byte isCanSale = productSkuBo.getIsCanSale();
			if (!DbConstants.isTrue(isCanSale)) {
				return ReturnUtils.error(ReturnCodes.SKU_CANNOT_SALE);
			}
		}

		Long shopId = productSkuBo.getShopId();
		Long productId = productSkuBo.getProductId();
		// TODO:暂时使用默认仓库
		ServiceReturnInfo serviceReturnInfo = productStockService.getProductStockByProductShopWarehouse(productId,
				shopId, DbConstants.DEFAULT_WAREHOUSE_ID);
		if (ServiceReturnUtils.isSuccess(serviceReturnInfo)) {
			if (serviceReturnInfo.getData() == null) {
				return ReturnUtils.error(ReturnCodes.SKU_STOCK_NOT_ENOUGH);
			}

			ProductSkuStockBo skuStockBo = (ProductSkuStockBo) serviceReturnInfo.getData();
			if (!DbConstants.isTrue(skuStockBo.getIsEnabled())) {
				return ReturnUtils.error(ReturnCodes.SKU_STOCK_NOT_ENOUGH);
			}

			Long realFrozenStockNum = skuStockBo.getRealFrozenStockNum();// 实际冻结库存
			Long realStockNum = skuStockBo.getRealStockNum();// 实际库存
			// 可用库存 = 实际库存 - 实际冻结库存
			Long availableStock = realStockNum - realFrozenStockNum;
			if (availableStock.intValue() < num) {
				return ReturnUtils.error(ReturnCodes.SKU_STOCK_NOT_ENOUGH);
			}
		}

		return ReturnUtils.success();
	}

}
